package com.ujiaoyu.security.jwt;

import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoder;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.stream.Collectors;

@Component
public class TokenProvider implements InitializingBean {

    private final String base64Secret;
    private final long tokenValidityMilliseconds;
    private Key key;

    public TokenProvider(
            @Value("${jwt.base64-secret}") String base64Secret,
            @Value("${jwt.tokenValidityMilliseconds}") long tokenValidityMilliseconds) {
        this.base64Secret = base64Secret;
        this.tokenValidityMilliseconds = tokenValidityMilliseconds;
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        byte[] keyByte= Decoders.BASE64.decode(base64Secret);
        this.key = Keys.hmacShaKeyFor(keyByte);
    }
    /**
     * 创建Token
     * @param authentication
     * @return
     */
    public String createToken(Authentication authentication){
        String authorites = authentication.getAuthorities()
                .stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.joining(","));
        long now = (new Date()).getTime();
        //过期时间
        Date validity = new Date(now + this.tokenValidityMilliseconds);

        //使用Jwts 工具生成Token
        String token = Jwts.builder()
                .setSubject(authentication.getName())//用户名
                .claim("auth", authorites)
                .signWith(key, SignatureAlgorithm.HS256)
                .setExpiration(validity)
                .compact();

        return token;
    }


    /**
     * 验证Token
     * @param token
     * @return
     */
    public boolean validateToken(String token){

        try {
            Jwts.parser().setSigningKey(this.key).parseClaimsJws(token);
            return  true;
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
        } catch (UnsupportedJwtException e) {
            e.printStackTrace();
        } catch (MalformedJwtException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }


        return false;
    }

    /**
     * 根据Token 获取认证对象
     * @param token
     * @return
     */
    public Authentication getAuthentication(String token){
        Claims claims = Jwts.parser().setSigningKey(this.key)
                .parseClaimsJws(token)
                .getBody();

        Collection<? extends GrantedAuthority> authorities=
                Arrays.stream(claims.get("auth").toString().split(","))
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());

        User userDetail = new User(claims.getSubject(),"",authorities);
        return new UsernamePasswordAuthenticationToken(userDetail,token,authorities);
    }



}
